package maple.thelittleredbook.recommendation.utils;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * LLM服务工具类
 * 纯粹的API调用工具，输入messages数组，输出字符串
 */
@Slf4j
@Component
public class LLMServiceUtil {

    @Value("${llm.api.base-url}")
    private String baseUrl;

    @Value("${llm.api.key}")
    private String apiKey;

    @Value("${llm.model:gpt-4o}")
    private String model;

    private final RestTemplate restTemplate;

    public LLMServiceUtil(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 调用LLM API
     *
     * @param messages 消息数组
     * @return LLM返回的字符串内容
     * @throws Exception 调用异常
     */
    public String callChatCompletion(List<ChatMessage> messages) throws Exception {
        try {
            // 构建请求体
            ChatCompletionRequest request = new ChatCompletionRequest();
            request.setModel(model);
            request.setStream(false);
            request.setMessages(messages);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(apiKey);

            HttpEntity<ChatCompletionRequest> entity = new HttpEntity<>(request, headers);

            // 发送请求
            log.debug("调用LLM API，模型: {}, 消息数量: {}", model, messages.size());
            ResponseEntity<ChatCompletionResponse> response = restTemplate.postForEntity(
                    baseUrl + "/chat/completions",
                    entity,
                    ChatCompletionResponse.class
            );

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new RuntimeException("LLM API调用失败，状态码: " + response.getStatusCode());
            }

            ChatCompletionResponse responseBody = response.getBody();
            if (responseBody == null || responseBody.getChoices() == null || responseBody.getChoices().isEmpty()) {
                throw new RuntimeException("LLM API返回数据为空");
            }

            String content = responseBody.getChoices().get(0).getMessage().getContent();
            log.debug("LLM API调用成功，返回内容长度: {}", content != null ? content.length() : 0);
            return content;

        } catch (Exception e) {
            log.error("调用LLM API失败", e);
            throw new Exception("LLM服务调用失败: " + e.getMessage(), e);
        }
    }

    /**
     * 便捷方法：发送单条用户消息
     *
     * @param userMessage 用户消息内容
     * @return LLM返回的字符串内容
     * @throws Exception 调用异常
     */
    public String callChatCompletion(String userMessage) throws Exception {
        return callChatCompletion(List.of(new ChatMessage("user", userMessage)));
    }

    // ==================== 内部类定义 ====================

    @Data
    public static class ChatCompletionRequest {
        private String model;
        private boolean stream;
        private List<ChatMessage> messages;
    }

    @Data
    public static class ChatMessage {
        private String role;
        private String content;

        public ChatMessage() {}

        public ChatMessage(String role, String content) {
            this.role = role;
            this.content = content;
        }
    }

    @Data
    static class ChatCompletionResponse {
        private String id;
        private String model;
        private String object;
        private long created;
        private List<Choice> choices;
        private Usage usage;
    }

    @Data
    static class Choice {
        private int index;
        private ChatMessage message;
        @JsonProperty("finish_reason")
        private String finishReason;
    }

    @Data
    static class Usage {
        @JsonProperty("prompt_tokens")
        private int promptTokens;
        @JsonProperty("completion_tokens")
        private int completionTokens;
        @JsonProperty("total_tokens")
        private int totalTokens;
    }
}